;
(function(win) {
	/**
	 * Engine.trigger(World);
	 * World.trigger(Scene);
	 * Scene.trigger(Spirit);
	 */

	var JadeEngine = {};

	JadeEngine.version = {};
	JadeEngine.version.number = "1.0.0.RELEASE";
	JadeEngine.version.author = "yumi@omuao.com";
	/**
	 * 继承
	 * @param {Object} Child
	 * @param {Object} Parent
	 */
	JadeEngine.extend = function(Child, Parent) {
		Child.prototype = Object.create(Parent.prototype);
		Child.prototype.constructor = Child;
		Child.__proto__ = Parent;
	}

	JadeEngine.define = function(callback) {
		(callback(JadeEngine));
	}

	win.JadeEngine = JadeEngine;

	var GUID = {};
	GUID.next = function() {
		function S4() {
			return(((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
		}

		function guid() {
			return(S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
		}
		return guid();
	}

	JadeEngine.define(function(engine) {
		//日志处理
		var Logger = function() {
			return new Logger.init();
		}
		var loggerProps = Logger.prototype;
		Logger.init = function() {};
		Logger.init.prototype = loggerProps;
		loggerProps.debug = function() {};
		loggerProps.error = function() {};
		loggerProps.warn = function() {};
		loggerProps.debuggerEnabled = false;
		loggerProps.errorEnabled = false;
		localStorage.warnEnabled = false;
		engine.Logger = Logger;
	});
	var logger = new JadeEngine.Logger();
	JadeEngine.logger = logger;

	JadeEngine.notifyArrayAndResult = function(array, callback, params) {
		var result = [];
		eval(" for(var num=0;num<array.length; num++){ try{ result.push(array[num]." + callback +
			"(params));	}catch(e){logger.warn('\\'" + callback + "\\' function is not found!');}}");
		return result;
	};

	JadeEngine.notifyAndResult = function(object, callback, params) {
		var result = {};
		eval(" try{ result = object." + callback + "(params);	}catch(e){logger.warn('\\'" + callback +
			"\\' function is not found!');}");
		return result;
	};

	JadeEngine.define(function(engine) {
		JadeEngine.EVENT_CONST_TYPE = {
			clock: {
				name: "CLOCK",
				method: "onClockEvent"
			},
			spirit: {
				name: "SPIRIT",
				method: "onSpiritEvent"
			},
		};
	});

	var Event = function() {};

	var EventContext = function(originator, params) {
		this.originator = originator;
		this.params = params;
	}

	EventContext.newInstance = function(originator, params) {
		return new EventContext(originator, params);
	}

	Event.newInstance = function(type, code, context) {
		var event = new Event();
		event.id = GUID.next();
		event.context = context;
		event.type = type;
		event.code = code;
		return event;
	}

	var JadeTimer = function(option) {
		//计数器
		var counter = 0;

		//执行任务的ID
		var taskId = null;

		//时间单位量。1000ms = 1秒
		var unit = 1000;

		//任务函数
		var task = null;

		//Timer名称
		var name = "default";

		/**
		 * 启动
		 */
		this.start = function start() {
			var that = this; // 保存当前对象this
			counter++;
			taskId = setTimeout(function() {
				that.stop();
				that.start();
			}, unit);
			if(task != null && typeof task === "function") {
				task(counter);
			}
			return this;
		};

		/**
		 * 完全终止
		 */
		this.stop = function(callback) {
			if(taskId != null && taskId != undefined) {
				counter = 0;
				clearTimeout(taskId);
			}
			if(callback != null && typeof task === "function") {
				callback();
			}
			return this;
		};

		/**
		 * 暂停终止
		 */
		this.suspend = function(callback) {
			if(taskId != null && taskId != undefined) {
				clearTimeout(taskId);
			}
			if(callback != null && typeof task === "function") {
				callback();
			}
			return this;
		};

		/**
		 * 获得Timer名称
		 */
		this.getName = function() {
			return name;
		};

		this.setName = function(_name) {
			if(typeof _name !== 'string') {
				throw "仅支持String 类型的参数！"
			}
			name = _name;
			return this;
		};

		this.setUnit = function(_unit) {
			if(typeof _unit !== 'number') {
				throw "仅支持Number 类型的参数！"
			}
			unit = _unit;
			return this;
		};

		this.getUnit = function() {
			return unit;
		};

		/**
		 * 设置任务
		 */
		this.setTask = function(_task) {
			if(typeof _task !== 'function') {
				throw "仅支持Funtion 类型的参数！"
			}
			task = _task;
			return this;
		};

		/**
		 * 获得当前任务
		 */
		this.getTask = function() {
			return task;
		};

		/**
		 * 获得计数器
		 */
		this.getCounter = function() {
			return counter;
		};

		/**
		 * 获得计数器
		 */
		this.setCounter = function(_counter) {
			counter = _counter;
		};

		if(option != null && typeof option !== "undefined") {
			this.setTask(option.task);
			this.setName(option.name);
			this.setUnit(option.unit);
		}

	};

	var TimeUnit = function() {
		return new TimeUnit.init();
	}
	var timeUnitProps = TimeUnit.prototype;
	TimeUnit.init = function() {};
	TimeUnit.init.prototype = timeUnitProps;
	timeUnitProps.CONST_MILLISECOND_TO_SECOND = 1000;
	timeUnitProps.CONST_SECOND_TO_MINUTE = 60;
	timeUnitProps.CONST_MINUTE_TO_HOUR = 60;
	timeUnitProps.CONST_HOUR_TO_DAY = 24;
	timeUnitProps.CONST_DAY_TO_LEAP_YEAR = 366;
	timeUnitProps.CONST_DAY_TO_YEAR = 365;
	timeUnitProps.CONST_DAY_TO_LEAP_YEAR_FEBRUARY = 29;
	timeUnitProps.CONST_DAY_TO_YEAR_FEBRUARY = 28;
	timeUnitProps.CONST_DAY_TO_SMALL_MONTH = 30;
	timeUnitProps.CONST_DAY_TO_LARGE_MONTH = 31;
	timeUnitProps.CONST_SEASON_START_MONTH = 3;
	timeUnitProps.CONST_SPRING_TO_SUMMER = 3;
	timeUnitProps.CONST_SUMMER_TO_AUTUMN = 3;
	timeUnitProps.CONST_AUTUMN_TO_WINTER = 3;
	timeUnitProps.CONST_WINTER_TO_SPRING = 3;
	timeUnitProps.CONST_MONTH_BIG = [1, 3, 5, 7, 8, 10, 12];
	timeUnitProps.CONST_MONTH_BIG_ZERO = 12;
	TimeUnit.CONST_MILLISECOND = 0;
	TimeUnit.CONST_SECOND = 1;
	TimeUnit.CONST_MINUTE = 2;
	TimeUnit.CONST_HOUR = 3;
	TimeUnit.CONST_DAY = 4;
	TimeUnit.CONST_MONTH = 5;
	TimeUnit.CONST_YEAR = 6;
	TimeUnit.CONST_SEASON_SPRING = 7;
	TimeUnit.CONST_SEASON_SUMMER = 8;
	TimeUnit.CONST_SEASON_AUTUMN = 9;
	TimeUnit.CONST_SEASON_WINTER = 10;
	Direction = {};
	//东
	Direction.CONST_EAST = 0;
	//西
	Direction.CONST_WEST = 1;
	//南
	Direction.CONST_SOUTH = 2;
	//北
	Direction.CONST_NORTH = 3;

	var Toolkit = function() {
		return new Toolkit.init();
	}
	var toolkitProps = Toolkit.prototype;
	Toolkit.init = function() {};
	Toolkit.init.prototype = toolkitProps;
	JadeEngine.Toolkit = Toolkit;
	Toolkit.GUID = GUID;
	Toolkit.Timer = JadeTimer;
	Toolkit.TimeUnit = TimeUnit;
	Toolkit.Direction = Direction;

	var Clock = function() {
		var clock = new Clock.init();
		clock.init();
		return clock;
	}
	var clockProps = Clock.prototype;
	Clock.init = function() {};
	Clock.init.prototype = clockProps;
	clockProps.init = function() {
		this.timeUnit = new TimeUnit();
		this.year = 0;
		this.month = 0;
		this.day = 0;
		this.yearDay = 0;
		this.hour = 0;
		this.minute = 0;
		this.second = 0;
		this.millisecond = 0;
	}

	clockProps.listener = function(type, value) {

	}

	clockProps.isLeapYear = function() {
		if(this.year % 4 == 0 && this.year % 100 != 0 || this.year % 400 == 0) {
			return true;
		}
		return false;
	}

	clockProps.isMonthBig = function(month) {
		var monthBig = this.timeUnit.CONST_MONTH_BIG;
		if(month == 0) {
			month = this.timeUnit.CONST_MONTH_BIG_ZERO;
		}
		for(var i = 0; i < monthBig.length; i++) {
			if(monthBig[i] == month) {
				return true;
			}
		}
		return false;
	}

	clockProps.defaultTask = function(world) {
		var that = this;
		var thatUnit = this.timeUnit;
		that.calcMonthDay = that.day;
		that.calcYearDay = that.day;
		that.calcMonth = that.month;
		var eventType = JadeEngine.EVENT_CONST_TYPE.clock.name;

		var type = JadeEngine.EVENT_CONST_TYPE.clock;

		var originator = world;

		var task = function() {
			var counter = that.millisecond + 1;
			var event = Event.newInstance(type.name, TimeUnit.CONST_MILLISECOND, EventContext.newInstance(originator, that.millisecond));
			JadeEngine.triggerWorld(type.method, event, world);
			JadeEngine.triggerSpirit(type.method, event, world);
			JadeEngine.triggerScene(type.method, event, world);
			that.listener(TimeUnit.CONST_MILLISECOND, that.millisecond);
			that.millisecond++;

			if(counter % thatUnit.CONST_MILLISECOND_TO_SECOND == 0) {
				event = Event.newInstance(type.name, TimeUnit.CONST_SECOND, EventContext.newInstance(originator, that.second));
				JadeEngine.triggerWorld(type.method, event, world);
				JadeEngine.triggerSpirit(type.method, event, world);
				JadeEngine.triggerScene(type.method, event, world);
				that.listener(TimeUnit.CONST_SECOND, that.second);
				that.second++;
			}

			var secondToMinute = thatUnit.CONST_SECOND_TO_MINUTE * thatUnit.CONST_MILLISECOND_TO_SECOND;
			if(counter % secondToMinute == 0) {
				event = Event.newInstance(type.name, TimeUnit.CONST_MINUTE, EventContext.newInstance(originator, that.minute));
				JadeEngine.triggerWorld(type.method, event, world);
				JadeEngine.triggerSpirit(type.method, event, world);
				JadeEngine.triggerScene(type.method, event, world);
				that.listener(TimeUnit.CONST_MINUTE, that.minute);
				that.minute++;
				that.second = 0;
			}

			var minuteToHour = thatUnit.CONST_SECOND_TO_MINUTE *
				thatUnit.CONST_MILLISECOND_TO_SECOND *
				thatUnit.CONST_MINUTE_TO_HOUR;

			if(counter % minuteToHour == 0) {
				event = Event.newInstance(type.name, TimeUnit.CONST_HOUR, EventContext.newInstance(originator, that.hour));
				JadeEngine.triggerWorld(type.method, event, world);
				JadeEngine.triggerSpirit(type.method, event, world);
				JadeEngine.triggerScene(type.method, event, world);
				that.listener(TimeUnit.CONST_HOUR, that.hour);
				that.hour++;
				that.minute = 0;
			}

			var hourToDay = thatUnit.CONST_SECOND_TO_MINUTE *
				thatUnit.CONST_MILLISECOND_TO_SECOND *
				thatUnit.CONST_MINUTE_TO_HOUR *
				thatUnit.CONST_HOUR_TO_DAY;

			if(counter % hourToDay == 0) {
				event = Event.newInstance(type.name, TimeUnit.CONST_DAY, EventContext.newInstance(originator, that.day));
				JadeEngine.triggerWorld(type.method, event, world);
				JadeEngine.triggerSpirit(type.method, event, world);
				JadeEngine.triggerScene(type.method, event, world);
				that.listener(TimeUnit.CONST_DAY, that.day);
				that.day++;
				that.calcMonthDay++;
				that.calcYearDay++;
				that.hour = 0;
			}

			var leapYear = that.isLeapYear();

			var findDayByMonth = function(month, leap) {

				if(month == 2 && leap) {
					return thatUnit.CONST_DAY_TO_LEAP_YEAR_FEBRUARY;
				}

				if(month == 2) {
					return thatUnit.CONST_DAY_TO_YEAR_FEBRUARY;
				}

				var monthFlag = that.isMonthBig(month);

				if(monthFlag) {
					return thatUnit.CONST_DAY_TO_LARGE_MONTH;
				}
				return thatUnit.CONST_DAY_TO_SMALL_MONTH;

			}
			var day = findDayByMonth(that.calcMonth, leapYear);

			if(day == that.calcMonthDay) {
				event = Event.newInstance(type.name, TimeUnit.CONST_MONTH, EventContext.newInstance(originator, that.month));
				JadeEngine.triggerWorld(type.method, event, world);
				JadeEngine.triggerSpirit(type.method, event, world);
				JadeEngine.triggerScene(type.method, event, world);
				that.listener(TimeUnit.CONST_MONTH, that.month);
				that.day = 0;
				that.calcMonthDay = 0;
				that.month++;
				that.calcMonth++;
			}

			var yearUnit = leapYear ? thatUnit.CONST_DAY_TO_LEAP_YEAR : thatUnit.CONST_DAY_TO_YEAR;

			if(that.calcYearDay == yearUnit) {
				event = Event.newInstance(type.name, TimeUnit.CONST_YEAR, EventContext.newInstance(originator, that.year));
				JadeEngine.triggerWorld(type.method, event, world);
				JadeEngine.triggerSpirit(type.method, event, world);
				JadeEngine.triggerScene(type.method, event, world);
				that.listener(TimeUnit.CONST_YEAR, that.year);
				that.year++;
				that.month = 0;
				that.day = 0;
				that.millisecond = 0;
				that.calcYearDay = 0;
				that.calcMonth = 1;
			}

			var spring = {};
			spring.start = thatUnit.CONST_SEASON_START_MONTH;
			spring.end = spring.start + thatUnit.CONST_SPRING_TO_SUMMER;

			if(spring.start == that.month) {
				event = Event.newInstance(type.name, TimeUnit.CONST_SEASON_SPRING, EventContext.newInstance(originator, that.month));
				JadeEngine.triggerWorld(type.method, event, world);
				JadeEngine.triggerSpirit(type.method, event, world);
				JadeEngine.triggerScene(type.method, event, world);
				that.listener(TimeUnit.CONST_SEASON_SPRING, that.month);
			}

			var summer = {};
			summer.start = spring.end;
			summer.end = summer.start + thatUnit.CONST_SUMMER_TO_AUTUMN;

			if(summer.start == that.month) {
				event = Event.newInstance(type.name, TimeUnit.CONST_SEASON_SUMMER, EventContext.newInstance(originator, that.month));
				JadeEngine.triggerWorld(type.method, event, world);
				JadeEngine.triggerSpirit(type.method, event, world);
				JadeEngine.triggerScene(type.method, event, world);
				that.listener(TimeUnit.CONST_SEASON_SUMMER, that.month);
			}

			var autumn = {};
			autumn.start = summer.end;
			autumn.end = autumn.start + thatUnit.CONST_AUTUMN_TO_WINTER;

			if(autumn.start == that.month) {
				event = Event.newInstance(type.name, TimeUnit.CONST_SEASON_AUTUMN, EventContext.newInstance(originator, that.month));
				JadeEngine.triggerWorld(type.method, event, world);
				JadeEngine.triggerSpirit(type.method, event, world);
				JadeEngine.triggerScene(type.method, event, world);
				that.listener(TimeUnit.CONST_SEASON_AUTUMN, that.month);
			}

			var winter = {};
			winter.start = autumn.end;
			winter.end = winter.start + thatUnit.CONST_WINTER_TO_SPRING;

			if(winter.start == that.month) {
				event = Event.newInstance(type.name, TimeUnit.CONST_SEASON_WINTER, EventContext.newInstance(originator, that.month));
				JadeEngine.triggerWorld(type.method, event, world);
				JadeEngine.triggerSpirit(type.method, event, world);
				JadeEngine.triggerScene(type.method, event, world);
				that.listener(TimeUnit.CONST_SEASON_WINTER, that.month);
			}
		}

		return task;
	}

	clockProps.getTask = function() {
		var task = this.getTimer().getTask();
		if(task != undefined && task != null) {
			return task;
		}
		task = this.defaultTask();
		this.getTimer().setTask(task);
	}

	clockProps.setTask = function(callback) {
		this.getTimer().setTask(callback);
	}

	clockProps.getTimer = function() {
		if(this.timer != null && typeof this.timer !== "undefined") {
			return this.timer;
		}
		var option = {
			"name": "虚拟时钟",
			"unit": 1,
			"task": function(e) {}
		};
		this.timer = new JadeTimer(option);
		return this.timer;
	}
	clockProps.start = function() {
		this.getTimer().start();
	};
	clockProps.stop = function() {
		this.getTimer().stop();
		this.init();
	};
	clockProps.suspend = function() {
		this.getTimer().suspend();
	};
	clockProps.resume = function() {
		this.getTimer().start();
	};

	//初始化世界
	var World = function() {
		return new World.init();
	};
	var worldProps = World.prototype;
	World.init = function() {};
	World.init.prototype = worldProps;
	JadeEngine.World = World;
	worldProps.getClock = function() {
		if(this.clock == null || typeof this.clock === "undefined") {
			this.clock = new Clock();
			this.clock.setTask(this.clock.defaultTask(this))
		}
		return this.clock;
	}
	worldProps.bindEvent = function(event) {

	}
	worldProps.start = function() {
		this.getClock().start();
	}
	worldProps.stop = function() {
		this.getClock().stop();
	}
	worldProps.suspend = function() {
		this.getClock().suspend();
	}
	worldProps.resume = function() {
		this.getClock().resume();
	}
	worldProps.setTimeCallBack = function(callback) {
		if(typeof callback === "function") {
			this.getClock().listener = callback;
		}
	}

	//世界时钟(ms)
	World.Clock = Clock;
	//世界垂直自转方向 
	worldProps.rotationDirection = Direction.CONST_EAST;
	//世界场景
	worldProps.scenes = [];
	worldProps.id = GUID.next();

	//设置物理引擎
	worldProps.setPhysicsEngine = function(physicsEngine) {
		throw "No physical engine driver detected.";
	};
	//获取物理引擎
	worldProps.getPhysicsEngine = function() {
		throw "No physical engine driver detected.";
	};

	//获取物理引擎版本信息
	worldProps.getPhysicsEngineVersionInfo = function() {
		throw "No physical engine driver detected.";
	};

	//设置天气引擎
	worldProps.setWeatherEngine = function(weatherEngine) {
		throw "No weather engine driver detected.";
	};
	//获取天气引擎
	worldProps.getWeatherEngine = function() {
		throw "No weather engine driver detected.";
	};

	//获取天气引擎版本信息
	worldProps.getWeatherEngineVersionInfo = function() {
		throw "No weather engine driver detected.";
	};

	//设置人工智能引擎
	worldProps.setAIEngine = function(weatherEngine) {
		throw "No AI engine driver detected.";
	};
	//获取人工智能引擎
	worldProps.getAIEngine = function() {
		throw "No AI engine driver detected.";
	};

	//获取人工智能引擎版本信息
	worldProps.getAIVersionInfo = function() {
		throw "No AI engine driver detected.";
	};

	//设置渲染引擎
	worldProps.setRenderEngine = function(weatherEngine) {
		throw "No render engine driver detected.";
	};

	//获取渲染引擎
	worldProps.getRenderEngine = function() {
		throw "No render engine driver detected.";
	};

	//获取渲染引擎版本信息
	worldProps.getRenderVersionInfo = function() {
		throw "No render engine driver detected.";
	};

	//设置媒体引擎
	worldProps.setMediaEngine = function(weatherEngine) {
		throw "No media engine driver detected.";
	};

	//获取媒体引擎
	worldProps.getMediaEngine = function() {
		throw "No media engine driver detected.";
	};

	//获取媒体引擎版本信息
	worldProps.getMediaVersionInfo = function() {
		throw "No media engine driver detected.";
	};

	//设置网络引擎
	worldProps.setNetworkEngine = function(weatherEngine) {
		throw "No network engine driver detected.";
	};

	//获取网络引擎
	worldProps.getNetworkEngine = function() {
		throw "No network engine driver detected.";
	};

	//获取网络引擎版本信息
	worldProps.getNetworkVersionInfo = function() {
		throw "No network engine driver detected.";
	};

	//设置控制引擎
	worldProps.setControlEngine = function(weatherEngine) {
		throw "No control engine driver detected.";
	};

	//获取控制引擎
	worldProps.getControlEngine = function() {
		throw "No control engine driver detected.";
	};

	//获取控制引擎版本信息
	worldProps.getControlVersionInfo = function() {
		throw "No control engine driver detected.";
	};

	//设置事件引擎
	worldProps.setEventEngine = function(eventEngine) {
		throw "No event engine driver detected.";
	};

	//获取事件引擎
	worldProps.getEventEngine = function() {
		throw "No event engine driver detected.";
	};

	//获取事件引擎版本信息
	worldProps.getEventVersionInfo = function() {
		throw "No event engine driver detected.";
	};

	worldProps.setRuntime = function(runtime) {
		this.runtime = runtime;
	}

	worldProps.getRuntime = function() {
		return this.runtime;
	}

	/**
	 * 事件引擎
	 */
	var EventEngine = function() {
		return new EventEngine.init();
	}
	var eventEngineProps = EventEngine.prototype;
	EventEngine.init = function() {};
	EventEngine.init.prototype = eventEngineProps;
	EventEngine.version = {};
	EventEngine.version.number = "1.0.0.RELEASE";
	EventEngine.version.author = "yumi@omuao.com";

	win.EventEngine = EventEngine;
	//设置事件引擎
	worldProps.setEventEngine = function(eventEngine) {
		if(!eventEngine instanceof EventEngine) {
			throw "EventEngine is not set";
		}
		eventEngine.setWordOptions(this);
		this.eventEngine = eventEngine;
		return this.eventEngine;
	};

	//获取事件引擎
	worldProps.getEventEngine = function() {
		if(this.eventEngine == null || typeof this.eventEngine === "undefined") {
			this.eventEngine = new EventEngine();
			this.eventEngine.setWorldOptions(this);
		}
		return this.eventEngine;
	};

	//获取事件引擎版本信息
	worldProps.getEventVersionInfo = function() {
		return EventEngine.version;
	};
	eventEngineProps.setWorldOptions = function(options) {
		this.worldOptions = options;
	}

	JadeEngine.each = function(elements, callback) {
		for(var i in elements) {
			callback(elements[i], i);
		}
	}

	/**
	 * 数据表
	 */
	var StatementTable = function() {
		this.elements = [];

		this.getElements = function() {
			return this.elements;
		}

		this.setElements = function(elements) {
			this.elements = elements;
		}

		this.findById = function(id) {
			var results = [];
			var that = this;
			JadeEngine.each(that.elements, function(element, index) {
				if(element.id == id) {
					results.push(element);
				}
			})
			return results[0];
		}

		this.find = function(condition) {
			var results = [];
			var that = this;
			JadeEngine.each(that.elements, function(element, index) {
				var flag = eval(condition);
				if(flag) {
					results.push(element);
				}
			})
			return results;
		}

		this.insert = function(element) {
			var that = this;
			JadeEngine.each(that.elements, function(element, index) {
				if(element.id == element.id) {
					throw "id is unique!"
				}
			});

			if(element instanceof Array) {
				for(var i in element) {
					this.elements.push(element[i]);
				}
			} else {
				this.elements.push(element);
			}

		}

		this.delete = function(condition) {
			var results = 0;
			var that = this;
			JadeEngine.each(that.elements, function(element, index) {
				var flag = eval(condition);
				if(flag) {
					results++;
					that.elements.splice(index);
				}
			})
			return results;
		}

		this.update = function(condition, element) {
			var results = 0;
			var that = this;
			JadeEngine.each(that.elements, function(element, index) {
				var flag = eval(condition, element);
				if(flag) {
					results++;
					that.elements[index] = element;
				}
			})
			return results;
		}
	}

	/**
	 * 运行时
	 */
	var Runtime = function() {
		return new Runtime.init();
	}
	var runtimeProps = Runtime.prototype;
	Runtime.init = function() {};
	Runtime.init.prototype = runtimeProps;

	JadeEngine.Runtime = Runtime;

	runtimeProps.setWorldTable = function(worldTable) {
		this.worldTable = worldTable;
	}

	runtimeProps.getWorldTable = function() {
		if(typeof this.worldTable === "undefined" || this.worldTable == null) {
			this.worldTable = new StatementTable();
		}
		return this.worldTable;
	}

	runtimeProps.sceneTable = new StatementTable();

	runtimeProps.getSceneTable = function() {
		return this.sceneTable;
	}

	runtimeProps.setSceneTable = function(sceneTable) {
		this.sceneTable = sceneTable;
	}

	runtimeProps.spiritTable = new StatementTable();

	runtimeProps.getSpiritTable = function() {
		return this.spiritTable;
	}

	runtimeProps.setSpiritTable = function(spiritTable) {
		this.spiritTable = spiritTable;
	}

	JadeEngine.getRuntime = function() {
		return new Runtime();
	}

	JadeEngine.run = function(world) {
		if(world instanceof World) {
			var runtime = JadeEngine.getRuntime();
			world.setRuntime(runtime);
			runtime.getWorldTable().insert(world);
			world.getRuntime().setSceneTable(world.getSceneTable());
			world.getRuntime().setSpiritTable(world.getSpiritTable());
		}
	}

	JadeEngine.triggerWorld = function(methodName, params, world) {
		if(world == null || typeof world === "undefined") {
			return;
		}
		if(world.getRuntime() == null || typeof world.getRuntime() === "undefined") {
			return;
		}
		if(typeof world.getRuntime().getWorldTable() === "undefined" || world.getRuntime().getWorldTable() == null) {
			return;
		}
		var elemnts = world.getRuntime().getWorldTable().getElements();
		JadeEngine.each(elemnts, function(elemnt, index) {
			JadeEngine.notifyAndResult(elemnt, methodName, params);
		});
	}

	JadeEngine.triggerScene = function(methodName, params, world) {
		if(world == null || typeof world === "undefined") {
			return;
		}
		if(world.getRuntime() == null || typeof world.getRuntime() === "undefined") {
			return;
		}
		if(typeof world.getRuntime().getSceneTable() === "undefined" || world.getRuntime().getSceneTable() == null) {
			return;
		}
		var elemnts = world.getRuntime().getSceneTable().getElements();
		JadeEngine.each(elemnts, function(elemnt, index) {
			JadeEngine.notifyAndResult(elemnt, methodName, params);
		});
	}

	JadeEngine.triggerSpirit = function(methodName, params, world) {
		if(world == null || typeof world === "undefined") {
			return;
		}
		if(world.getRuntime() == null || typeof world.getRuntime() === "undefined") {
			return;
		}
		if(typeof world.getRuntime().getSpiritTable() === "undefined" || world.getRuntime().getSpiritTable() == null) {
			return;
		}
		var elemnts = world.getRuntime().getSpiritTable().getElements();
		JadeEngine.each(elemnts, function(elemnt, index) {
			JadeEngine.notifyAndResult(elemnt, methodName, params);
		});
	}

	worldProps.sceneTable = new StatementTable();

	worldProps.getSceneTable = function() {
		return this.sceneTable;
	}

	worldProps.setSceneTable = function(sceneTable) {
		this.sceneTable = sceneTable;
	}

	worldProps.spiritTable = new StatementTable();

	worldProps.getSpiritTable = function() {
		return this.spiritTable;
	}

	worldProps.setSpiritTable = function(spiritTable) {
		this.spiritTable = spiritTable;
	}

	worldProps.setWorldTable = function(worldTable) {
		this.worldTable = worldTable;
	}

	worldProps.getWorldTable = function() {
		return this.worldTable;
	}

	worldProps.addSpirit = function(spirit) {
		this.getSpiritTable().insert(spirit);
	}

	worldProps.addScene = function(scene) {
		this.getSceneTable().insert(scene);
		if(scene != null || typeof scene !== "undefined") {
			if(scene.getRuntime() == null || typeof scene.getRuntime() === "undefined") {
				scene.setRuntime(this.getRuntime());
			}
		}
	}

	JadeEngine.StatementTable = StatementTable;

	/**
	 * 绘图
	 */
	var Graphics2D = function(x, y) {
		return new Graphics2D.init();
	}
	var graphics2DProps = Graphics2D.prototype;
	Graphics2D.init = function(x, y) {
		this.screen = new Screen(x, y);
	};
	Graphics2D.init.prototype = graphics2DProps;

	/**
	 * 屏幕
	 * @param {Object} width 宽
	 * @param {Object} height 高
	 */
	var Screen = function(width, height) {
		return new Screen.init(width, height);
	}
	var screenProps = Screen.prototype;
	Screen.init = function(width, height) {
		this.width = width;
		this.height = height;
		this.bitData = [];
		for(var x = 0; x < width; x++) {
			for(var y = 0; y < height; y++) {
				var color = new Color(0, 0, 0, 1);
				var point = new Point(x, y);
				this.bitData[x][y] = new Pixel(point, color);
			}
		}
	};
	Screen.init.prototype = screenProps;
	screenProps.toBitImage = function() {
		var image = BitImage();
		image.width = this.width;
		image.height = this.height;
		this.bitData = [];
		for(var x = 0; x < this.width; x++) {
			for(var y = 0; y < this.height; y++) {
				image.setPixel(this.bitData[x][y]);
			}
		}
		return image;
	}
	Graphics2D.Screen = Screen;

	/**
	 * 点
	 * @param {Object} x x坐标
	 * @param {Object} y y左边
	 */
	var Point = function(x, y) {
		return new Point.init(x, y);
	}
	var pointProps = Point.prototype;
	Point.init = function(x, y) {
		if(arguments.length == 1) {
			this.x = arguments[0].x;
			this.y = arguments[0].y;
			return;
		}
		this.x = x;
		this.y = y;
	};

	pointProps.valueOfSelf = function(point) {
		this.x = point.x;
		this.y = point.y;
	}

	pointProps.clone = function() {
		return new Point(this.x, this.y);
	}
	Point.init.prototype = pointProps;
	Graphics2D.Point = Point;

	/**
	 * 颜色
	 * @param {Object} r 红色
	 * @param {Object} g 绿色
	 * @param {Object} b 蓝色
	 * @param {Object} a 透明度
	 */
	var Color = function(r, g, b, a) {
		return new Color.init(r, g, b, a);
	}
	var colorProps = Color.prototype;
	Color.init = function(r, g, b, a) {
		if(arguments.length == 1) {
			this.r = arguments[0].r;
			this.g = arguments[0].g;
			this.b = arguments[0].b;
			this.a = arguments[0].a;
			return;
		}
		this.r = r;
		this.g = g;
		this.b = b;
		this.a = a;
	};

	colorProps.valueOfRgbaStyleString = function(num) {
		if(num.indexOf("#") != -1) {
			this.valueOfRgbString(num);
			return;
		}

		if(num.indexOf("rgba(")) {
			var temp = num.substring(num.indexOf("rgba("), num.length - 1);
			var rgabArray = temp.split(",");
			this.r = parseInt(rgabArray[0]);
			this.g = parseInt(rgabArray[1]);
			this.b = parseInt(rgabArray[2]);
			this.a = parseFloat(rgabArray[3]);
		}
	}

	colorProps.valueOfArgbString = function(num) {
		var temp = num;
		if(num.indexOf("#") == 0) {
			temp = num.replace("#", "");
		}
		this.valueOfArgb(parseInt(temp, 16));
	}

	colorProps.valueOfRgbString = function(num) {
		var temp = num;
		if(num.indexOf("#") == 0) {
			temp = num.replace("#", "");
		}
		this.valueOfRgb(parseInt(temp, 16));
	}

	colorProps.valueOfRgb = function(num) {
		var num = parseInt(num);
		var rgb = this.integerToRgb(num);
		this.r = rgb.r;
		this.g = rgb.g;
		this.b = rgb.b;
	}

	colorProps.valueOfArgb = function(num) {
		var num = parseInt(num);
		var rgb = this.integerToRgb(num);
		var alpha = ((this.getAlpha(num) / 100) * 0.255).toFixed(3);
		this.r = rgb.r;
		this.g = rgb.g;
		this.b = rgb.b;
		this.a = alpha;
	}

	/**
	 * RGB转整形数字
	 * @param {Number} r
	 * @param {Number} g
	 * @param {Number} b
	 */
	colorProps.rgbToInteger = function(r, g, b) {
		r = r & 0xff;
		g = g & 0xff;
		b = g & 0xff;
		return(r << 16) | (r << 8) | b;
	};

	/**
	 * 整形数字转RGB
	 * @param {Number} num 值
	 */
	colorProps.integerToRgb = function(num) {
		var rgb = {};
		rgb.b = num & 0xff; //B
		rgb.g = num >> 8 & 0xff; //G
		rgb.r = num >> 16 & 0xff; //R
		return rgb;
	};

	/**
	 * ARGB 转 RGB
	 * @param {Object} argb ARGB值
	 */
	colorProps.argbToRgb = function(argb) {
		return argb & 0xffffff;
	};

	/**
	 * 获得Alpha 值
	 * @param {Object} argb 
	 */
	colorProps.getAlpha = function(argb) {
		return argb >> 24 & 0xff;
	};

	/**
	 * 不足2位则补0
	 * @param {Object} value 值
	 */
	colorProps.appendZero = function(value) {
		return value.length == 0 ? "00" : value.length == 1 ? "0" + value : value;
	}

	/**
	 * 转RGB值
	 * @param {Object} num
	 */
	colorProps.toRgbString = function(num) {
		var rgb = this.integerToRgb(num);
		var r = this.appendZero(rgb.r.toString(16));
		var g = this.appendZero(rgb.g.toString(16));
		var b = this.appendZero(rgb.b.toString(16));
		return r + g + b;
	};

	/**
	 * 转RGBA值
	 * @param {Object} num
	 */
	colorProps.toRgbAlphaString = function(num) {
		var rgb = this.integerToRgb(num);
		var alpha = ((this.getAlpha(num) / 100) * 0.255).toFixed(3);
		return "rgba(" + rgb.r + "," + rgb.g + "," + rgb.b + "," + alpha + ")";
	};

	/**
	 * 随机颜色
	 */
	colorProps.randomColor = function() {
		return Math.floor(Math.random() * 0xffffff);
	};

	/**
	 * 随机带有透明通道的颜色
	 */
	colorProps.randomArgbColor = function() {
		return Math.floor(Math.random() * 0xffffffff);
	};

	/**
	 * argb16进制 值 rgb值
	 * @param {Object} hexColor
	 */
	colorProps.rgbHexToInteger = function(hexColor) {
		return parseInt(hexColor.replace("#", ""), 16);
	};

	/**
	 * 获得随机颜色
	 */
	colorProps.getRandomColor = function() {
		var rgb = this.integerToRgb(pt.randomColor());
		return "rgb(" + rgb.r + "," + rgb.g + "," + rgb.b + ")";
	};

	/**
	 * 获得随机带有透明通道的颜色
	 */
	colorProps.getRandomAlphaColor = function() {
		var argb = this.randomArgbColor();
		var rgb = this.integerToRgb(argb);
		var alpha = ((pt.getAlpha(argb) / 100) * 0.255).toFixed(3);
		return "rgba(" + rgb.r + "," + rgb.g + "," + rgb.b + "," + alpha + ")";
	};

	colorProps.valueOfSelf = function(color) {
		this.r = color.r;
		this.g = color.g;
		this.b = color.b;
		this.a = color.a;
	}

	colorProps.clone = function() {
		return new Color(this.r, this.g, this.b, this.a);
	}
	Color.init.prototype = colorProps;
	Graphics2D.Color = Color;

	/**
	 * 像素
	 * @param {Object} point 位置点
	 * @param {Object} color 颜色
	 * @param {Object} data 额外数据
	 */
	var Pixel = function(point, color, data) {
		return new Pixel.init(point, color, data);
	}

	/**
	 * 像素
	 */
	var pixelProps = Pixel.prototype;
	Pixel.init = function(point, color, data) {
		if(arguments.length == 1) {
			this.point = arguments[0].point;
			this.color = arguments[0].color;
			this.data = arguments[0].data;
			return;
		}
		this.point = point;
		this.color = color;
		this.data = data;
	};
	Pixel.init.prototype = pixelProps;

	pixelProps.valueOfSelf = function(pixel) {
		this.point = pixel.point;
		this.color = pixel.color;
		this.data = pixel.data;
	}

	pixelProps.clone = function() {
		var point = this.point.clone();
		var color = this.color.clone();
		var data = this.data.clone();
		return new Pixel(point, color, data);
	}
	Graphics2D.Pixel = Pixel;

	var IconImage = function(tagImage) {
		return new IconImage.init(tagImage);
	}
	var iconImageProps = IconImage.prototype;

	IconImage.init = function(tagImage) {
		if(tagImage instanceof Image) {
			this.image = tagImage;
			return;
		}
		if(typeof tagImage === "string") {
			this.image = new Image();
			this.image.src = tagImage;
			return;
		}
		throw "tagImage is not Image";
	};

	iconImageProps.setSrc = function(src) {
		this.image.src = src;
	}

	iconImageProps.getSrc = function() {
		return this.image.src;
	}

	iconImageProps.setWidth = function(width) {
		this.image.width = width;
	}

	iconImageProps.getWidth = function() {
		return this.image.width;
	}

	iconImageProps.setHeight = function(height) {
		this.image.height = height;
	}

	iconImageProps.getHeight = function() {
		return this.image.height;
	}

	iconImageProps.getImage = function() {
		return this.Image;
	}

	iconImageProps.setImage = function(image) {
		this.image = image;
	}

	iconImageProps.clone = function() {
		var image = new Image();
		image.src = this.getSrc();
		image.width = this.getWidth();
		image.height = this.getHeight();
		return new IconImage(image);
	}

	IconImage.init.prototype = iconImageProps;
	Graphics2D.IconImage = IconImage;

	/**
	 * 位图
	 * @param {Object} pixelDatas 数据
	 * @param {Object} width 宽
	 * @param {Object} height 高
	 */
	var BitImage = function(width, height, pixelDatas) {
		return new BitImage.init(width, height, pixelDatas);
	}
	var bitImageProps = BitImage.prototype;
	BitImage.init = function(width, height, pixelDatas) {
		this.width = width;
		this.height = height;
		this.bitData = [];
		this.each(function(that, x, y) {
			if(typeof that.bitData[x] === "undefined") {
				that.bitData[x] = [];
			}
			var point = new Point(x, y);
			var color = new Color(0, 0, 0, 1);
			that.bitData[x][y] = new Pixel(point, color, null);
		});

		if(pixelDatas != null || typeof pixelDatas === "undefined") {
			for(var i in pixelDatas) {
				var pixel = pixelDatas[i];
				this.setPixel(pixel);
			}
		}
	};
	BitImage.init.prototype = bitImageProps;

	bitImageProps.each = function(callback) {
		for(var x = 0; x < this.width; x++) {
			for(var y = 0; y < this.height; y++) {
				callback(this, x, y);
			}
		}
	}

	bitImageProps.getPixel = function(x, y) {
		var point = new Point(x, y);
		if(arguments.length == 1) {
			point = arguments[1];
		}
		return this.bitData[point.x][point.y];
	}
	bitImageProps.setPixel = function(pixel) {
		this.bitData[pixel.point.x][pixel.point.y] = pixel;
	}
	bitImageProps.setPixelColor = function() {
		var pixel = null;
		if(arguments.length == 1 && arguments[0] instanceof Pixel) {
			pixel = arguments[0];
		}

		if(arguments.length == 2 && arguments[0] instanceof Point) {
			pixel = new Pixel(arguments[0], arguments[1]);
		}

		if(arguments.length == 3 && arguments[2] instanceof Color) {
			var point = new Point(arguments[0], arguments[1]);
			pixel = new Pixel(point, arguments[2]);
		}

		if(arguments.length == 6) {
			var point = new Point(arguments[0], arguments[1]);
			var color = new Point(arguments[2], arguments[3], arguments[4], arguments[5]);
			pixel = new Pixel(point, color);
		}

		var bitPixel = this.bitData[x][y];
		if(bitPixel == null || typeof bitPixel === "undefined") {
			bitPixel = pixel;
			return;
		}
		bitPixel.color = pixel.color;
	}

	bitImageProps.valueOfSelf = function(bitImage) {
		this.width = bitImage.width;
		this.height = bitImage.height;
		this.bitData = bitImage.bitData;
	}

	bitImageProps.clone = function() {
		var bitImage = new BitImage(this.width, this.height);
		var clone = this;
		bitImage.each(function(that, x, y) {
			if(typeof that.bitData[x] === "undefined") {
				that.bitData[x] = [];
			}
			that.bitData[x][y] = clone.bitData[x][y].clone();
		});
	}

	Graphics2D.BitImage = BitImage;

	/**
	 * 瓦片
	 */
	var Tile = function(x, y, width, height) {
		return new Tile.init(x, y, width, height);
	}
	var tileProps = Tile.prototype;
	Tile.init = function(x, y, width, height) {
		this.src = null;
		if(arguments.length == 0) {
			this.x = arguments[0].x;
			this.y = arguments[0].y;
			this.width = arguments[0].width;
			this.height = arguments[0].height;
			var image = new Image(this.width, this.height);
			this.image = new IconImage(image);
			return;
		}

		if(arguments.length == 2) {
			this.x = 0;
			this.y = 0;
			this.width = arguments[0];
			this.height = arguments[1];
			var image = new Image(this.width, this.height);
			this.image = new IconImage(image);
			return;
		}
		this.x = x;
		this.y = y;
		this.width = width;
		this.height = height;
		var image = new Image(this.width, this.height);
		this.image = new IconImage(image);
	};
	Tile.init.prototype = tileProps;

	tileProps.setNext = function(tile) {
		this.next = tile;
	}

	tileProps.getImage = function() {
		if(this.image == null || typeof this.image === "undefined") {
			var image = new Image(this.width, this.height);
			this.image = new IconImage(image);
		}
		return this.image;
	}

	tileProps.setSrc = function(src) {
		this.src = src;
		this.image.setSrc(src);
	}

	tileProps.getSrc = function() {
		return this.src;
	}

	tileProps.valueOfSelf = function(tile) {
		this.x = tile.x;
		this.y = tile.y;
		this.width = tile.width;
		this.height = tile.height;
		this.image = tile.image;
	}

	tileProps.clone = function() {
		var tile = new Tile(this.x, this.y, this.width, this.height);
		tile.image = this.image.clone();
		if(this.next != null && typeof this.next !== "undefined") {
			tile.next = this.next.clone();
		}
		return tile;
	}

	Graphics2D.Tile = Tile;

	/**
	 * 瓦片地图
	 */
	var TileMap = function(cols, rows) {
		return new TileMap.init(cols, rows);
	}
	var tileMapProps = TileMap.prototype;
	TileMap.init = function(cols, rows) {
		this.cols = cols;
		this.rows = rows;
		this.datas = [];
		this.each(function(that, x, y) {
			if(typeof that.datas[x] === "undefined") {
				that.datas[x] = [];
			}
			that.datas[x][y] = new Tile();
		});
	};

	tileMapProps.each = function(callback) {
		for(var x = 0; x < this.cols; x++) {
			for(var y = 0; y < this.rows; y++) {
				callback(this, x, y);
			}
		}
	}

	tileMapProps.valueOfSelf = function(tileMap) {
		this.cols = tileMap.cols;
		this.rows = tileMap.rows;
		this.datas = tileMap.datas;
	}

	tileMapProps.clone = function() {
		var tileMap = new TileMap(this.cols, this.rows);
		var clone = this;
		tileMap.each(function(that, x, y) {
			if(typeof that.datas[x] === "undefined") {
				that.datas[x] = [];
			}
			that.datas[x][y] = clone.datas[x][y].clone();
		});
	}
	TileMap.init.prototype = tileMapProps;
	Graphics2D.TileMap = TileMap;
	JadeEngine.Graphics2D = Graphics2D;
	JadeEngine.graphics2D = new Graphics2D();

	JadeEngine.define(function(engine) {

		var eventType = engine.EVENT_CONST_TYPE.spirit.name;

		var type = engine.EVENT_CONST_TYPE.spirit;

		/**
		 * 精灵
		 */
		var Spirit = function() {
			return new Spirit.init();
		}
		var spiritProps = Spirit.prototype;
		Spirit.init = function() {};
		Spirit.init.prototype = spiritProps;

		spiritProps.id = GUID.next();

		/**
		 * 触发事件
		 * @param {Object} world 事件
		 * @param {Object} eventType 事件类型
		 */
		spiritProps.trigger = function(world, eventType) {
			var originator = world;
			var event = Event.newInstance(type.name, eventType,
				EventContext.newInstance(originator, this));
			engine.triggerWorld(type.method, event, world);
			engine.triggerSpirit(type.method, event, world);
			engine.triggerScene(type.method, event, world);
		}

		engine.Spirit = Spirit;

	});

	JadeEngine.define(function(engine) {
		var World_ = engine.World;

		/**
		 * 场景
		 */
		var Scene = function() {
			return new Scene.init();
		}
		var sceneProps = Scene.prototype;
		Scene.init = function() {};
		Scene.init.prototype = sceneProps;

		sceneProps.id = GUID.next();
		engine.extend(Scene.init, engine.World);
		engine.Scene = Scene;
	});

}(window));